package com.system.boot.rbac.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.system.api.SuperInterface;
import com.system.api.rbac.entity.bo.MakeCompanyBo;
import com.system.api.rbac.entity.po.SysPermission;
import com.system.api.rbac.entity.po.SysRole;
import com.system.api.rbac.entity.vo.PermissionListVo;
import com.system.boot.rbac.converter.PermissionConverter;
import com.system.boot.rbac.mapper.PermissionMapper;
import com.system.boot.rbac.mapper.RolePermissionRelationMapper;
import com.system.boot.rbac.service.PermissionService;
import com.system.common.constant.SystemConstant;
import com.system.common.enums.SuperEnum;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.yang.common.core.exception.BaseException;
import org.yang.common.i18n.constant.I18nMessageConstant;
import org.yang.common.utils.jwt.JwtTokenAnalysisUtli;
import org.yang.database.orm.entity.BaseModel;
import org.yang.database.orm.entity.BaseQuery;
import org.yang.database.orm.entity.Options;

import java.util.*;
import java.util.stream.Collectors;

/**
 *  
 * @author: lslands
 * @description:   
 * @version：v1.0
 * @date:    2024/6/13 14:02
 */
@Service
@RequiredArgsConstructor
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, SysPermission> implements PermissionService, SuperInterface<SysPermission> {


    private final RolePermissionRelationMapper rolePermissionRelationMapper;
    @Override
    public void isExists(Long companyId,String variable,String param) throws BaseException {
       if(StringUtils.isBlank(variable) && StringUtils.isBlank(param)){
           throw new BaseException(I18nMessageConstant.VALIDATION_EMPTY);
       }
       if(baseMapper.getExists(companyId, variable,param)){
           throw new BaseException(BaseException.REPEAT,param);
       }
    }

    @Override
    public List<Options<Integer>> listOptions(Long companyId, List<String> roleCodes) throws BaseException {
        List<SysPermission> permissionList;
        if(JwtTokenAnalysisUtli.isRoot()){
            List<? extends Number> companyList = List.of(companyId, 0);
            LambdaQueryWrapper<SysPermission> wrapper = new LambdaQueryWrapper<SysPermission>()
                    .select(BaseModel::getId, SysPermission::getName)
                    .in(SysPermission::getCompanyId, companyList)
                    .eq(BaseModel::getEnabled, 1);
            permissionList = baseMapper.selectList(wrapper);
        }else{
            permissionList=baseMapper.selectPermByRoles(companyId,roleCodes);
        }
        return Optional.of(permissionList.stream().map(x -> new Options<Integer>(x.getId().intValue(), x.getName())).toList())
                .orElse(new ArrayList<Options<Integer>>());

    }




    @Override
    public int handInsert(SysPermission record) throws BaseException {
        Long companyId = Optional.of(record.getCompanyId()).orElse(JwtTokenAnalysisUtli.companyId());
        this.isExists(companyId, "name", record.getName());
        this.isExists(companyId, "code", record.getCode());
        return baseMapper.insert(record);
    }

    @Override
    public int handUpdateById(SysPermission record) throws BaseException {
        SysPermission oldResult =
                Optional.ofNullable(baseMapper.selectById(record.getId()))
                        .orElseThrow(() -> new BaseException(BaseException.NULL));
        if (!Objects.equals(record, oldResult)) {
            Long companyId = Optional.of(record.getCompanyId()).orElse(JwtTokenAnalysisUtli.companyId());
            if (!record.getName().equals(oldResult.getName())) {
                this.isExists(companyId, "name", record.getName());
            }
            if(!record.getCode().equals(oldResult.getCode())){
                this.isExists(companyId, "code", record.getCode());
            }
            return baseMapper.updateById(record);
        }
        return 1;
    }

    @Override
    public int handEnabledById(Long id, Integer enabled, Integer revision) throws BaseException {
        SysPermission oldResult =
                Optional.ofNullable(baseMapper.selectById(id))
                        .orElseThrow(() -> new BaseException(BaseException.NULL));
        if (null == enabled) {
            throw new BaseException(I18nMessageConstant.VALIDATION_STATUS_EMPTY);
        }
        if (enabled.equals(oldResult.getEnabled())) {
            return 1;
        }
        return baseMapper.updateById(new SysPermission(id, enabled, revision));
    }

    @Override
    public Page<SysPermission> getPage(BaseQuery query, SysPermission record) throws BaseException {
        Page<SysPermission> page= new Page<>(query.getCurrent(), query.getSize());
        if(JwtTokenAnalysisUtli.isRoot()){
            List<? extends Number> companyList = List.of(record.getCompanyId(), 0);
            LambdaQueryWrapper<SysPermission> wrapper = new LambdaQueryWrapper<SysPermission>()
                    .select(BaseModel::getId,SysPermission::getName,SysPermission::getCode,SysPermission::getDescription,BaseModel::getEnabled)
                    .like(StringUtils.isNotBlank(record.getName()), SysPermission::getName, record.getName())
                    .eq(record.getEnabled()!=null,SysPermission::getEnabled,record.getEnabled())
                    .in(SysPermission::getCompanyId,companyList)
                    .orderByDesc(BaseModel::getId);
            return baseMapper.selectPage(page, wrapper);
        }
        List<SysPermission> sysPermissions =
                rolePermissionRelationMapper.selectPageByRoles(record, JwtTokenAnalysisUtli.roles());
        page.setRecords(sysPermissions);
        page.setTotal(sysPermissions.size());
        return page;
    }

    @Override
    public int deleteOne(Long id) throws BaseException {
        if( Objects.isNull(id)){
            throw new BaseException("id cannot be null");
        }
        return baseMapper.deleteById(id);
    }

    @Override
    public int deleteBatch(Boolean delete, List<Long> ids) throws BaseException {
        if(ids.isEmpty()){
            return 0;
        }
        return delete?baseMapper.deleteBatch(ids):baseMapper.deleteBatchIds(ids);
    }
}
